using BlogExample.Core.Domain;
using BlogExample.Core.Services;
using FubuMVC.Tests;
using NUnit.Framework;
using Rhino.Mocks;

namespace BlogExample.Tests.Services
{
	[TestFixture]
	public class DisplayServiceTester
	{
		private DisplayService _displayService;
		private IDisplayStrategy _strategy;
		private IDisplayStrategy _strategy2;

		[SetUp]
		public void Setup()
		{
			_strategy = MockRepository.GenerateStub<IDisplayStrategy>();
			_strategy2 = MockRepository.GenerateStub<IDisplayStrategy>();
			_displayService = new DisplayService(new[] { _strategy, _strategy2 });
		}

		[Test]
		public void should_return_default_empty_entity_description_if_no_strategy_matched()
		{
			_displayService.GetDisplayFor(new DomainEntity()).ShouldEqual("");
		}

		[Test]
		public void should_return_default_strategy_no_matter_what()
		{
			_displayService.FindStrategyFor(new DomainEntity()).ShouldBeOfType<DefaultDisplayStrategy>();
		}

		[Test]
		public void should_match_a_strategy_by_matches_method()
		{
			_strategy.Stub(x => x.Matches(null)).IgnoreArguments().Return(true);
			_displayService.FindStrategyFor(new DomainEntity()).ShouldBeTheSameAs(_strategy);
		}

		[Test]
		public void should_match_first_strategy()
		{
			_strategy.Stub(x => x.Matches(null)).IgnoreArguments().Return(true);

			_displayService.FindStrategyFor(new DomainEntity());

			_strategy2.AssertWasNotCalled(s => s.Matches(null), o => o.IgnoreArguments());
		}

		[Test]
		public void should_check_all_strategies_for_matches()
		{
			_strategy2.Stub(x => x.Matches(null)).IgnoreArguments().Return(true);
			_displayService.FindStrategyFor(new DomainEntity()).ShouldBeTheSameAs(_strategy2);
		}

		[Test]
		public void should_return_display_from_matched_strategy()
		{
			string name = "Skippy";
			_strategy.Stub(x => x.Matches(null)).IgnoreArguments().Return(true);
			_strategy.Stub(x => x.GetEntityDescription(null)).IgnoreArguments().Return(name);

			_displayService.GetDisplayFor(new DomainEntity()).ShouldEqual(name);
		}

		[Test]
		public void should_only_call_display_on_matched_method_and_no_others()
		{
			_strategy.Stub(x => x.Matches(null)).IgnoreArguments().Return(true);
			_strategy.Stub(x => x.GetEntityDescription(null)).IgnoreArguments().Return(null);

			_displayService.GetDisplayFor(new DomainEntity());

			_strategy2.AssertWasNotCalled(x => x.GetEntityDescription(null), o => o.IgnoreArguments());
		}
	}
}